package org.example.classtopia.Controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.classtopia.Common.Result.Result;
import org.example.classtopia.Model.dto.AiSessionCreateDTO;
import org.example.classtopia.Model.dto.AiSessionUpdateDTO;
import org.example.classtopia.Model.vo.AiMessageHistoryVO;
import org.example.classtopia.Model.vo.AiSessionListVO;
import org.example.classtopia.Model.vo.AiSessionVO;
import org.example.classtopia.Model.vo.AiMessageVO;
import org.example.classtopia.Service.AiChatSessionHistoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.memory.ChatMemory;

@RestController
@Slf4j
@RequestMapping("/ai")
@Tag(name = "AI辅助学习")
@RequiredArgsConstructor
public class AiController {

    private final AiChatSessionHistoryService aiChatSessionHistoryService;

    @Autowired(required = false)
    private OpenAiChatModel chatModel;

    @Autowired(required = false)
    private org.springframework.ai.chat.client.ChatClient chatClient;

    @Autowired(required = false)
    private org.springframework.ai.chat.memory.ChatMemory chatMemory;

    /**
     * 获取聊天会话列表
     * 
     * @param userId 用户ID
     * @param page   页码
     * @param size   每页大小
     * @return 会话列表
     */
    @Operation(summary = "获取聊天会话列表")
    @GetMapping("/sessions")
    public Result<AiSessionListVO> getSessionList(
            @Parameter(description = "用户ID") @RequestParam(required = false) Long userId,
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer page,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "20") Integer size) {
        log.info("获取会话列表，用户ID: {}, 页码: {}, 每页大小: {}", userId, page, size);
        return aiChatSessionHistoryService.getSessionList(userId, page, size);
    }

    /**
     * 获取会话消息历史
     * 
     * @param sessionId 会话ID
     * @param userId    用户ID
     * @param page      页码
     * @param size      每页大小
     * @return 消息历史
     */
    @Operation(summary = "获取会话消息历史")
    @GetMapping("/sessions/{sessionId}/messages")
    public Result<AiMessageHistoryVO> getSessionMessages(
            @Parameter(description = "会话ID") @PathVariable String sessionId,
            @Parameter(description = "用户ID") @RequestParam(required = false) Long userId,
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer page,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "50") Integer size) {
        log.info("获取会话消息历史，会话ID: {}, 用户ID: {}, 页码: {}, 每页大小: {}", sessionId, userId, page, size);
        return aiChatSessionHistoryService.getSessionMessages(sessionId, userId, page, size);
    }

    /**
     * 创建聊天会话
     * 
     * @param createSessionDTO 创建会话参数
     * @return 新建会话信息
     */
    @Operation(summary = "创建聊天会话")
    @PostMapping("/sessions")
    public Result<AiSessionVO> createSession(@RequestBody AiSessionCreateDTO createSessionDTO) {
        log.info("创建聊天会话: {}", createSessionDTO);
        // 直接调用，不做token校验
        // 取出 userId 并传递给 service，强转为 Long，避免类型不一致
        Integer userIdInt = createSessionDTO.getUserId();
        Long userIdLong = userIdInt == null ? null : userIdInt.longValue();
        return aiChatSessionHistoryService.createSession(createSessionDTO, userIdLong);
    }

    /**
     * 更新会话标题
     * 
     * @param sessionId        会话ID
     * @param updateSessionDTO 新标题参数
     * @return 操作结果
     */
    @Operation(summary = "更新会话标题")
    @PutMapping("/sessions/{sessionId}")
    public Result<Void> updateSessionTitle(
            @Parameter(description = "会话ID") @PathVariable String sessionId,
            @RequestBody AiSessionUpdateDTO updateSessionDTO) {
        log.info("更新会话标题，会话ID: {}, 新标题: {}", sessionId, updateSessionDTO.getTitle());
        return aiChatSessionHistoryService.updateSessionTitle(sessionId, updateSessionDTO.getTitle());
    }

    /**
     * 删除会话
     * 
     * @param sessionId 会话ID
     * @return 操作结果
     */
    @Operation(summary = "删除会话")
    @DeleteMapping("/sessions/{sessionId}")
    public Result<Void> deleteSession(@Parameter(description = "会话ID") @PathVariable String sessionId) {
        log.info("删除会话，会话ID: {}", sessionId);
        return aiChatSessionHistoryService.deleteSession(sessionId);
    }

    /**
     * AI 聊天接口
     * 
     * @param prompt    用户输入内容
     * @param sessionId 会话ID
     * @return AI回复
     */
    @Operation(summary = "AI 聊天")
    @CrossOrigin(origins = "*")
    @PostMapping(value = "/chat")
    public Result<AiMessageVO> chat(@RequestParam String prompt, @RequestParam String sessionId) {
        log.info("AI聊天请求，prompt: {}, sessionId: {}", prompt, sessionId);
        // 直接调用，不做token校验和用户查找
        return aiChatSessionHistoryService.getChatResponse(prompt, sessionId, null);
    }

    /**
     * 测试AI聊天接口
     * 
     * @return 测试消息
     */
    @Operation(summary = "测试AI聊天")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/chat/test")
    public Result<AiMessageVO> testChat() {
        log.info("测试AI聊天接口被调用");
        try {
            AiMessageVO testVO = new AiMessageVO();
            testVO.setId("test-123");
            testVO.setRole("assistant");
            testVO.setContent("这是一个测试消息");
            testVO.setTimestamp("2025-07-01 15:30:00");
            log.info("测试消息创建成功");
            return Result.success(testVO);
        } catch (Exception e) {
            log.error("测试失败", e);
            return Result.error("测试失败：" + e.getMessage());
        }
    }

    /**
     * 测试AI服务状态
     * 
     * @return AI服务状态描述
     */
    @Operation(summary = "测试AI服务状态")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/test-ai")
    public Result<String> testAi() {
        try {
            if (chatModel != null) {
                log.info("AI服务已启用，chatModel类型: {}", chatModel.getClass().getSimpleName());
                return Result.success("AI服务已启用，模型类型: " + chatModel.getClass().getSimpleName());
            } else {
                log.warn("AI服务未启用，chatModel为null");
                return Result.success("AI服务未启用，chatModel为null");
            }
        } catch (Exception e) {
            log.error("测试AI服务失败", e);
            return Result.error("测试失败: " + e.getMessage());
        }
    }

    /**
     * 测试AI模型调用
     * 
     * @return AI回复内容
     */
    @Operation(summary = "测试AI模型")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/test-model")
    public Result<String> testModel() {
        try {
            if (chatModel != null) {
                log.info("开始测试AI模型调用");

                // 使用正确的Spring AI API
                UserMessage userMsg = new UserMessage("你好，请简单介绍一下你自己");
                Prompt prompt = new Prompt(userMsg);

                ChatResponse response = chatModel.call(prompt);
                String aiReply = response.getResult().getOutput().getText();

                log.info("AI模型测试成功: {}", aiReply);
                return Result.success("AI调用成功：" + aiReply);
            } else {
                return Result.error("chatModel为null");
            }
        } catch (Exception e) {
            log.error("AI模型测试失败", e);
            return Result.error("AI调用失败：" + e.getMessage());
        }
    }

    /**
     * 调试AI服务，检查Bean和环境变量状态
     * 
     * @return 调试信息
     */
    @Operation(summary = "调试AI服务")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/debug")
    public Result<String> debugAi() {
        try {
            StringBuilder debug = new StringBuilder();

            // 检查Bean注入状态
            debug.append("=== AI Bean 状态检查 ===\n");
            debug.append("ChatModel: ").append(chatModel != null ? "已注入" : "未注入(null)").append("\n");

            // 检查环境变量
            debug.append("=== 环境变量检查 ===\n");
            String apiKey = System.getenv("OPENAI_API_KEY");
            debug.append("OPENAI_API_KEY: ").append(apiKey != null ? "已设置(长度:" + apiKey.length() + ")" : "未设置")
                    .append("\n");

            // 尝试直接调用AI
            debug.append("=== AI调用测试 ===\n");
            if (chatModel != null) {
                try {
                    log.info("开始测试AI模型直接调用");
                    org.springframework.ai.chat.messages.UserMessage userMsg = new org.springframework.ai.chat.messages.UserMessage(
                            "测试消息，请回复'收到'");
                    org.springframework.ai.chat.prompt.Prompt prompt = new org.springframework.ai.chat.prompt.Prompt(
                            userMsg);

                    org.springframework.ai.chat.model.ChatResponse response = chatModel.call(prompt);
                    String aiReply = response.getResult().getOutput().getText();

                    debug.append("AI调用成功: ").append(aiReply).append("\n");
                } catch (Exception e) {
                    debug.append("AI调用失败: ").append(e.getMessage()).append("\n");
                    log.error("AI调用测试失败", e);
                }
            } else {
                debug.append("无法测试：ChatModel为null\n");
            }

            return Result.success(debug.toString());
        } catch (Exception e) {
            log.error("调试AI服务失败", e);
            return Result.error("调试失败: " + e.getMessage());
        }
    }

    /**
     * 测试通义千问API连接
     * 
     * @return 测试结果
     */
    @Operation(summary = "测试通义千问API连接")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/test-qwen")
    public Result<String> testQwenConnection() {
        try {
            StringBuilder result = new StringBuilder();

            // 检查环境变量
            String apiKey = System.getenv("OPENAI_API_KEY");
            result.append("API Key: ").append(apiKey != null ? "已设置" : "未设置").append("\n");

            // 检查Spring AI自动配置的chatModel
            result.append("ChatModel Bean: ").append(chatModel != null ? "已注入" : "未注入").append("\n");

            if (chatModel != null) {
                try {
                    // 直接使用已注入的chatModel进行测试
                    org.springframework.ai.chat.messages.UserMessage userMsg = new org.springframework.ai.chat.messages.UserMessage(
                            "测试消息，请简单回复");
                    org.springframework.ai.chat.prompt.Prompt prompt = new org.springframework.ai.chat.prompt.Prompt(
                            userMsg);

                    org.springframework.ai.chat.model.ChatResponse response = chatModel.call(prompt);
                    String aiReply = response.getResult().getOutput().getText();

                    result.append("AI调用成功: ").append(aiReply).append("\n");
                } catch (Exception e) {
                    result.append("AI调用失败: ").append(e.getMessage()).append("\n");
                    log.error("AI调用失败", e);
                }
            }

            return Result.success(result.toString());

        } catch (Exception e) {
            log.error("测试通义千问API连接失败", e);
            return Result.error("测试失败: " + e.getMessage());
        }
    }

    /**
     * 测试聊天接口内部逻辑
     * 
     * @return AI回复内容
     */
    @Operation(summary = "测试聊天接口内部逻辑")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/test-chat-internal")
    public Result<String> testChatInternal() {
        try {
            String sessionId = "test-session-" + System.currentTimeMillis();
            String prompt = "你好，这是内部测试";

            log.info("开始测试聊天接口内部逻辑");
            Result<AiMessageVO> result = aiChatSessionHistoryService.getChatResponse(prompt, sessionId, null);

            if (result.getCode() == 200) {
                return Result.success("内部逻辑测试成功，AI回复: " + result.getData().getContent());
            } else {
                return Result.error("内部逻辑测试失败: " + result.getMessage());
            }
        } catch (Exception e) {
            log.error("测试聊天接口内部逻辑失败", e);
            return Result.error("测试失败: " + e.getMessage());
        }
    }

    /**
     * 检查Service层Bean状态
     * 
     * @return Service层Bean状态信息
     */
    @Operation(summary = "检查Service层Bean状态")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/debug-service")
    public Result<String> debugService() {
        try {
            StringBuilder status = new StringBuilder();
            status.append("=== Service层Bean状态检查 ===\n");
            status.append("AiChatSessionHistoryService: ")
                    .append(aiChatSessionHistoryService != null ? "已注入" : "未注入(null)").append("\n");

            // 直接调用Service的检查方法
            if (aiChatSessionHistoryService != null) {
                org.example.classtopia.Service.Impl.AiChatSessionHistoryServiceImpl serviceImpl = (org.example.classtopia.Service.Impl.AiChatSessionHistoryServiceImpl) aiChatSessionHistoryService;
                String serviceBeanStatus = serviceImpl.checkAiBeanStatus();
                status.append(serviceBeanStatus);
            }

            return Result.success(status.toString());
        } catch (Exception e) {
            log.error("检查Service层Bean状态失败", e);
            return Result.error("检查失败: " + e.getMessage());
        }
    }

    /**
     * 修复数据库表结构，返回SQL指令
     * 
     * @return 修复指令
     */
    @Operation(summary = "修复数据库表结构")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/fix-database")
    public Result<String> fixDatabase() {
        try {
            StringBuilder result = new StringBuilder();

            // 这里应该使用DataSource来执行SQL，但为了简化，我们提供手动修复指令
            result.append("=== 数据库修复指令 ===\n");
            result.append("请在数据库中执行以下SQL语句：\n\n");
            result.append("1. 删除旧表：\n");
            result.append("DROP TABLE IF EXISTS SPRING_AI_CHAT_MEMORY;\n\n");
            result.append("2. 创建新表：\n");
            result.append("CREATE TABLE IF NOT EXISTS SPRING_AI_CHAT_MEMORY (\n");
            result.append("    conversation_id VARCHAR(255) NOT NULL,\n");
            result.append("    content TEXT NOT NULL,\n");
            result.append("    type VARCHAR(50) NOT NULL,\n");
            result.append("    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n");
            result.append("    metadata TEXT,\n");
            result.append("    PRIMARY KEY (conversation_id, timestamp),\n");
            result.append("    INDEX idx_conversation_id (conversation_id),\n");
            result.append("    INDEX idx_timestamp (timestamp)\n");
            result.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;\n\n");
            result.append("3. 或者重启应用，让Spring AI自动创建表\n");

            return Result.success(result.toString());
        } catch (Exception e) {
            log.error("生成数据库修复指令失败", e);
            return Result.error("修复失败: " + e.getMessage());
        }
    }

    /**
     * 检查数据库表结构，返回SQL指令
     * 
     * @return 检查指令
     */
    @Operation(summary = "检查数据库表结构")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/check-database-table")
    public Result<String> checkDatabaseTable() {
        try {
            StringBuilder result = new StringBuilder();
            result.append("=== 数据库表结构检查 ===\n");

            // 这里应该使用DataSource来查询表结构
            result.append("请在数据库中手动执行以下查询来检查表结构：\n\n");
            result.append("1. 检查表是否存在：\n");
            result.append("SHOW TABLES LIKE 'SPRING_AI_CHAT_MEMORY';\n\n");
            result.append("2. 检查表结构：\n");
            result.append("DESCRIBE SPRING_AI_CHAT_MEMORY;\n\n");
            result.append("3. 检查表中数据：\n");
            result.append("SELECT COUNT(*) FROM SPRING_AI_CHAT_MEMORY;\n\n");
            result.append("期望的表结构应该包含：id(主键), conversation_id, content, type, timestamp, metadata\n");

            return Result.success(result.toString());
        } catch (Exception e) {
            log.error("检查数据库表结构失败", e);
            return Result.error("检查失败: " + e.getMessage());
        }
    }

    /**
     * 清除指定会话的ChatMemory
     * 
     * @param sessionId 会话ID
     * @return 操作结果
     */
    @Operation(summary = "清除ChatMemory")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/clear-memory")
    public Result<String> clearMemory(@RequestParam String sessionId) {
        try {
            // 通过Service层清除ChatMemory
            var serviceImpl = (org.example.classtopia.Service.Impl.AiChatSessionHistoryServiceImpl) aiChatSessionHistoryService;
            var clearResult = serviceImpl.clearSessionMessages(sessionId);

            if (clearResult.getCode() == 200) {
                return Result.success("成功清除会话 " + sessionId + " 的ChatMemory");
            } else {
                return Result.error("清除失败: " + clearResult.getMessage());
            }
        } catch (Exception e) {
            log.error("清除ChatMemory失败", e);
            return Result.error("清除失败: " + e.getMessage());
        }
    }

    /**
     * 专门测试ChatClient+ChatMemory功能
     * 
     * @return 测试结果
     */
    @Operation(summary = "专门测试ChatClient+ChatMemory功能")
    @CrossOrigin(origins = "*")
    @GetMapping(value = "/test-chatclient-memory")
    public Result<String> testChatClientMemory() {
        try {
            StringBuilder result = new StringBuilder();
            result.append("=== ChatClient + ChatMemory 测试 ===\n");

            // 检查Bean注入状态
            result.append("ChatClient Bean: ").append(chatClient != null ? "已注入" : "未注入").append("\n");
            result.append("ChatMemory Bean: ").append(chatMemory != null ? "已注入" : "未注入").append("\n");

            if (chatClient != null && chatMemory != null) {
                try {
                    String testSessionId = "test-memory-" + System.currentTimeMillis();

                    // 第一次调用
                    result.append("\n--- 第一次调用 ---\n");
                    var response1 = chatClient.prompt()
                            .user("你好，我叫测试用户")
                            .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, testSessionId))
                            .call();
                    String reply1 = response1.content();
                    result.append("回复1: ").append(reply1).append("\n");

                    // 第二次调用（测试记忆）
                    result.append("\n--- 第二次调用（测试记忆） ---\n");
                    var response2 = chatClient.prompt()
                            .user("我叫什么名字？")
                            .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, testSessionId))
                            .call();
                    String reply2 = response2.content();
                    result.append("回复2: ").append(reply2).append("\n");

                    // 检查记忆是否保存
                    result.append("\n--- 检查记忆内容 ---\n");
                    var memories = chatMemory.get(testSessionId);
                    result.append("记忆中的消息数量: ").append(memories.size()).append("\n");
                    for (int i = 0; i < memories.size(); i++) {
                        result.append("消息").append(i + 1).append(": ").append(memories.get(i).getText()).append("\n");
                    }

                    return Result.success(result.toString());

                } catch (Exception e) {
                    result.append("ChatClient+ChatMemory调用失败: ").append(e.getMessage()).append("\n");
                    result.append("异常类型: ").append(e.getClass().getSimpleName()).append("\n");
                    log.error("ChatClient+ChatMemory调用失败", e);
                    return Result.error(result.toString());
                }
            } else {
                result.append("ChatClient或ChatMemory未正确注入\n");
                return Result.error(result.toString());
            }

        } catch (Exception e) {
            log.error("测试ChatClient+ChatMemory失败", e);
            return Result.error("测试失败: " + e.getMessage());
        }
    }

}
